/*
 * FileParsing.java - parser en xml file med medarbejdere og printer deres attributter
 * 
 * Dette program benytter sig af Document klassen, der indeholder en komplet xml fils attributter, det såkaldte DOM
 * (Document Object Model).
 * Denne metode er nem at bruge, men uhensigtsmæssig hvis der benyttes større filer, da alt xml data
 * befinder sig i hukommelsen på én gang. Ved større filer (adskillige Mb), kan det anbefales at benytte en
 * SAX parser, som benytter sig af callbacks (i stil med for eksempel ActionListeners i AWT/Swing) til at 
 * informere om at et givent tag er fundet i filen. SAX parseren er sværere at benytte, men til gengæld bruger 
 * den begrænset hukommelse. 
 * Se eventuelt http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/parsers/SAXParser.html
 * 
 * @Author jacob
*/

package xml;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


public class FileParsing
{
	private class Medarbejder
	{
		private final String navn;
		private final int alder;
		private final String afdeling;
		
		
		public Medarbejder(String navn, int alder, String afdeling)
		{
			this.navn = navn;
			this.alder = alder;
			this.afdeling = afdeling;
		}
		
		public String getNavn()
		{
			return navn;
		}
		
		public int getAlder()
		{
			return alder;
		}
		
		public String getAfdeling()
		{
			return afdeling;
		}
		
		@Override
		public String toString()
		{
			StringBuilder sb = new StringBuilder();
			
			sb.append("Navn: " + navn + "\n");
			sb.append("Alder: " + alder + "\n");
			sb.append("Afdeling: " + afdeling + "\n");
			
			return sb.toString();
		}
	}
	
	private class MedarbejderListe implements Iterable<Medarbejder>
	{
		private final LinkedList<Medarbejder> liste = new LinkedList<Medarbejder>();
		
		
		public void add(Medarbejder m)
		{
			liste.add(m);
		}
		
		@Override
		public Iterator<Medarbejder> iterator()
		{
			return liste.iterator();
		}
	}
	
	private final String XML_FIL = "ansatte.xml";
	
	public static void main(String[] args)
	{
		new FileParsing().demo();
	}
	
	private void exit(String message)
	{
		System.err.println(message);
		System.exit(1);
	}
	
	private void demo()
	{		
		try
		{
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.parse(new File(XML_FIL));
			
			MedarbejderListe liste = parseDocument(document);
			
			System.out.println("Medarbejdere fundet " + XML_FIL + ":");
			for (Medarbejder medarbejder : liste)
			{
				System.out.println(medarbejder);
			}
		}
		
		catch (ParserConfigurationException pce)
		{
			// sker aldrig (7-9-13)
			// se http://java.sun.com/j2se/1.4.2/docs/api/javax/xml/parsers/ParserConfigurationException.html
			exit(pce.getMessage());
		}
		
		catch (SAXException se)
		{
			// malformed xml (syntax fejl)
			exit("Syntax fejl: " + se.getMessage());
		}
		
		catch (IOException ioe)
		{
			exit("Fejl: " + XML_FIL + " kunne ikke åbnes");
		}
	}
	
	private MedarbejderListe parseDocument(Document document)
	{
		MedarbejderListe liste = new MedarbejderListe();
		
		Element topElement = document.getDocumentElement();
		NodeList nl = topElement.getElementsByTagName("medarbejder");
		
		if (nl == null || nl.getLength() == 0)
			exit("Dokumentet indeholder ingen <medarbejder> tags");
		
		for (int i = 0; i < nl.getLength(); i ++)
		{
			// for hvert <medarbejder> tag, læs attributter og kopier dem ind i et nyt Medarbejder objekt
			Element element = (Element) nl.item(i);
			
			liste.add(parseMedarbejder(element));
		}
		
		
		return liste;
	}
	
	private Medarbejder parseMedarbejder(Element element)
	{
		String navn = getStringValue(element, "navn");
		int alder = getIntValue(element, "alder");
		String afdeling = getStringValue(element, "afdeling");
		
		return new Medarbejder(navn, alder, afdeling);
		
	}
	
	private String getStringValue(Element element, String tag)
	{
		String stringValue = null;
		NodeList nl = element.getElementsByTagName(tag);
		
		if (nl != null && nl.getLength() > 0)
		{
			stringValue = ((Element) nl.item(0)).getFirstChild().getNodeValue();
		}
		
		return stringValue;
	}
	
	private int getIntValue(Element element, String tag)
	{
		return Integer.parseInt(getStringValue(element, tag));
	}
	


}